<?php
namespace App\Common\Server\Api;

use App\Common as com;
use App as nameApp;
use App\Common\Server\Api as nameApi;
use App\Common\Server\Api\Gateway as nameGateway;
use Psr\Http\Message\ServerRequestInterface;

class Gateway extends nameApi\Base {

	/**
	 * api请求对象
	 * @var nameGateway\ApiRequest
	 */
	protected nameGateway\ApiRequest $apiRequest;

	/**
	 * api路由
	 * @var nameGateway\ApiRouter
	 */
	private nameGateway\ApiRouter $apiRouter;

	/**
	 * Gateway constructor.
	 * @param Gateway\ApiRequest $apiRequest api请求对象
	 */
	public function __construct( nameGateway\ApiRequest $apiRequest ) {
		$this->apiRequest = $apiRequest;
		//
		parent::__construct();
	}

	/**
	 * 网关->处理器
	 * @return nameGateway\ApiResponse api响应对象
	 */
	public function handle():com\Lib\Api\Response {
		try {
			if( $this->apiRouter()->apiClassEntity()->tokenConfig_IsNeedToken ) {
				// 检测token信息
				$checkTokenRes = $this->checkTokenInfo();
				if( $checkTokenRes !== true ) {
					return $checkTokenRes;
				}
			}
			// 执行api
			// return $this->excApi( $this->apiRequest );
			return $this->excApi();
		}catch( \Throwable $e ){
			return nameApi\Exception::new( $e )->toApiResponse();
		}
	}

	/**
	 * 检测token信息
	 * @return Gateway\ApiResponse|bool [true]检测通过 [{Gateway\ApiResponse}]检测失败并返回失败信息
	 * @throws
	 */
	private function checkTokenInfo(  ):Gateway\ApiResponse|bool {
		// 请求时间戳验证
		/*
		if( ( com\Lib\Fun\Time::getTime() - $this->apiRequest->apiData()->getTimestamp() ) > nameGateway\ApiRequest::$timestampTimeoutS  ){
			return nameGateway\ApiResponse::instanceOfCommon( com\Lib\Err\Code::$apiSerTimestamp );
		}
		*/
		// 检查token是否存在
		if( ! $this->apiRequest->accessToken()->isValid() ) {
			return nameGateway\ApiResponse::instanceOfCommon( com\Lib\Err\Code::$apiSerTokenNoExist );
		}
		// api签名验证
		if( $this->apiRequest->sign()->isCheckSign() && ! $this->apiRequest->sign()->checkSign() ){
			return nameGateway\ApiResponse::instanceOfCommon( com\Lib\Err\Code::$apiSerSignError );
		}
		// api权限验证
		if( $this->apiRouter()->apiClassEntity()->tokenConfig_IsCheckAuth && ! $this->apiRequest->auth()->check() ) {
			return nameGateway\ApiResponse::instanceOfCommon( com\Lib\Err\Code::$apiSerNoUseAuth);
		}
		//
		return true;
	}

	/**
	 * 获取api路由对象
	 * @return nameGateway\ApiRouter
	 */
	public function apiRouter(  ):nameGateway\ApiRouter {
		if( ! isset( $this->apiRouter ) ){
			$this->apiRouter = (new nameGateway\ApiRouter( $this->apiRequest ));
		}
		//
		return $this->apiRouter;
	}

	/**
	 * @return Gateway\ApiRequest
	 */
	public function goApiRequest(  ):nameGateway\ApiRequest {
		return $this->apiRequest;
	}

	/**
	 * 执行api
	 * @return Gateway\ApiResponse api响应对象
	 * @throws
	 */
	private function excApi():Gateway\ApiResponse {
		// 调用api路由并执行
		if( $this->apiRequest->apiData()->isApiParams() ){
			// 多参数模式
			return $this->excApiOfApiParams();
		}else{
			// 单参数模式
			return $this->apiRouter()->excApi();
		}
	}

	/**
	 * 执行api(多参数模式)
	 * @return Gateway\ApiResponse
	 */
	private function excApiOfApiParams(  ):Gateway\ApiResponse {
		$apiResponseArrayGroups = [];
		foreach( $this->apiRequest->apiData()->getApiParamsObj() as $apiParamKey => $apiParamObj ){
			try {
				$apiResponse = $this->apiRouter()->excApi( $apiParamObj->get() );
			}catch( \Throwable $e ){
				$apiResponse = nameApi\Exception::new( $e )->toApiResponse();
			}
			// 是否独立输出
			if( $this->apiRequest->apiData()->getIsIndependentRes() ){
				$apiResponseArrayGroups[ $apiParamKey ] = $apiResponse->getApiResponse()->toArray();
			}else{
				if( $apiResponse->getCode() != com\Lib\Api::$varApiCode_Success ){
					// 发生错误，终止执行。返回已执行的数据
					$apiResponseArrayGroups["_errorApiParam"] = $apiParamObj->get();
					return nameGateway\ApiResponse::instanceOfError( $apiResponse->getCode(), $apiResponse->getMsg(), $apiResponseArrayGroups );
				}
				//
				$apiResponseArrayGroups[ $apiParamKey ] = $apiResponse->getData();
			}
		}
		return nameGateway\ApiResponse::instanceOfSuccess( $apiResponseArrayGroups );
	}

	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * 初始化网关（webApi）
	 * @param ServerRequestInterface|null $request
	 * @return Gateway\Ext\WebApi
	 * @throws
	 */
	public static function newClassOfWebApi( ServerRequestInterface|null $request = null ):Gateway\Ext\WebApi {
		$request = $request ?? com\Lib\Hyperf\Request::getRequestOrFail();
		return new nameGateway\Ext\WebApi( $request );
	}

}
